package com.qf.shopping.common;

import com.qf.shopping.common.Constants;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**Controller的父类，抽出的公共的方法
 * @author 三旬
 * @version 1.0  2022/9/13
 */

public class DisatpcherServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1.获取用户请求路径
        String requestURI = req.getRequestURI();
        //2.根据URI获取到用户调用的方法名
        String actionName = getActionName(requestURI);
        //3.先获得当前类所有的方法（仅包括子类所有的方法，不包括父类的方法），再找出对应的方法
        Method actionMethod = findActionMethod(actionName);
        //4.判断是否存在
        if(actionMethod != null){
            //方法名存在，调用该方法，得到结果（转发 or 重定向）
            String result = invokeActionMethod(actionMethod,req,resp);
            //根据结果做出响应（转发 or 重定向）
            if(result != null && !"".equals(result)){
                responseClient(result,req,resp);
            }
        }else{
            System.out.println(actionName+"请求未找到！");
        }
    }

    /**
     * 根据结果做出响应（转发 or 重定向）
     * @param result
     * @param req
     * @param resp
     */
    private void responseClient(String result, HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1.将结果拆分为：转跳方式和转跳的页面
        String[] split = result.split(":");
        //转跳方式
        String type = split[0];
        //转跳页面(失败提示语)
        String page = split[1];
        //2.根据拆分结果做出响应
        if(Constants.FORWARD.equals(type)){
            req.getRequestDispatcher(req.getContextPath()+"/"+page).forward(req,resp);
        }else if(Constants.REDIRECT.equals(type)){
            resp.sendRedirect(req.getContextPath()+"/"+page);
        }else if(Constants.SCRIPT.equals(type)){
            resp.getWriter().println("<script>alert("+page+");window.history.back(-1);</script>");
        }else if(Constants.JSON.equals(type)){
            //以json格式响应内容(防止出现多个“ ：”分割符，以第一个“ ：”分割)
            //获得第一个 ：的位置
            Integer index = result.indexOf(":");
            //以第一个 ：进行分割
            String json = result.substring( index + 1);
            //响应信息
            resp.getWriter().write(json);
        }
    }

    /**
     * 调用该方法，得到返回结果
     * @param actionMethod
     * @param req
     * @param resp
     * @return
     */
    private String invokeActionMethod(Method actionMethod, HttpServletRequest req, HttpServletResponse resp) {
        try {
            return (String) actionMethod.invoke(this,req,resp);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 先获得当前类所有的方法（仅包括子类所有的方法，不包括父类的方法），再找出对应的方法
     * @param actionName
     * @return
     */
    private Method findActionMethod(String actionName) {
        //1.先获得当前类所有的方法（仅包括子类所有的方法，不包括父类的方法）
        Method[] methods = this.getClass().getDeclaredMethods();
        //找出对应的方法
        for (int i = 0; i < methods.length; i++) {
            Method method =methods[i];
            if(method.getName().equals(actionName)){
                return method;
            }
        }
        return null;
    }

    /**
     * 根据URI获取到用户调用的方法
     * @param requestURI
     * @return
     */
    private String getActionName(String requestURI) {
        String actionName = requestURI.substring(requestURI.lastIndexOf("/")+1);
        System.out.println("接收了方法:"+actionName);
        return actionName;
    }
}
